/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipti.br.tag.bean;

import org.ipti.br.tag.bo.ActorBO;
import org.ipti.br.tag.bo.DisciplineBO;
import org.ipti.br.tag.bo.OrganizationBO;
import org.ipti.br.tag.bo.PerformanceBO;
import org.ipti.br.tag.bo.UnityBO;
import org.ipti.br.tag.entity.Actor;
import org.ipti.br.tag.entity.Discipline;
import org.ipti.br.tag.entity.Human;
import org.ipti.br.tag.entity.Performance;
import org.ipti.br.tag.entity.SimpleFrequency;
import org.ipti.br.tag.entity.Unity;
import org.ipti.br.tag.entity.enums.Reference;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Digits;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import org.ipti.br.tag.util.ServiceUtil;

/**
 *
 * @author israel
 */
@ManagedBean
@ViewScoped
public class PerformanceMB extends AppBaseBean {

    @Inject private SessionBean sessionBean;
    @Inject private OrganizationBO organizationBO;
    @Inject private UnityBO unityBO;
    @Inject private ActorBO actorBO;
    @Inject private DisciplineBO disciplineBO;
    @Inject private PerformanceBO performanceBO;
    private boolean configureGradesVisible = false;
    
    @Digits(integer = 1, fraction = 0, message = "Informe um valor inteiro entre 1 e 9")
    @Max(value = 9, message = "Informe um valor inteiro entre 1 e 9")
    @Min(value = 1, message = "Informe um valor inteiro entre 1 e 9")
    private int grandeQuantity = 11;
    private Long organizationID;
    private Long unityID;
    private Long disciplineID;
    private List<SelectItem> unityList;
    private List<SelectItem> disciplineList;
    private List<Actor> actorList;
    private static final int DEFAULT_BUFFER_SIZE = 10240;

    public void init() {
        unityList = new ArrayList<SelectItem>();
        unityList.add(new SelectItem(null, "Selecione uma unidade"));
        if (organizationID != null) {
            for (Unity unity : unityBO.activatedUnities(
                    unityBO.unityChildrenPerOrganization2(
                    sessionBean.getLoggedActor().getUnity().getId(), organizationID))) {
                unityList.add(new SelectItem(unity.getId(), unity.getName()));
            }
        }
    }
    
    public String getOrganizationName() {
        return organizationBO.find(organizationID).getName();
    }

    public void listDisciplines() {
        actorList = new ArrayList<Actor>();
        disciplineList = new ArrayList<SelectItem>();
        disciplineList.add(new SelectItem(null, " "));
        disciplineID = null;
        for (Discipline discipline : disciplineBO.searchDisciplinesPerUnity(unityID)) {
            disciplineList.add(new SelectItem(discipline.getId(), discipline.getName()));
        }
    }

    public void configureGrades() {
        Integer gradeCount = performanceBO.gradesQuantityForUnityDiscipline(disciplineID, Reference.UNITY, unityID);

        if (gradeCount == null) {
            //configureGradesVisible = true;
            //grandeQuantity = 0;
            //return;

            saveConfiguration();
            return;
        }

        //grandeQuantity = gradeCount.intValue();
        loadTable();
        loadGrades();
        //configureGradesVisible = false;
    }

    public void saveConfiguration() {
        loadTable();
        Discipline disciplineAux = new Discipline();
        disciplineAux.setId(disciplineID);

        for (Actor actor : actorList) {
            actor.setPerformances(new ArrayList<Performance>());
            for (int i = 1; i <= grandeQuantity; i++) {
                Performance performance = new Performance(actor, disciplineAux,
                        Reference.UNITY, unityID, 0F);
                performance.setSeq(i);
                performanceBO.create(performance);
                actor.getPerformances().add(performance);
            }
        }
        configureGradesVisible = false;
    }

    public void loadTable() {
        actorList = actorBO.searchActorPerUnitiesMatriculated(unityBO.find(unityID));
    }

    public String firstGrade(int actorPosition) {
        return String.format("%.2f", (actorList.get(actorPosition).getPerformances().get(0).getGrade()
                + actorList.get(actorPosition).getPerformances().get(1).getGrade()) / 2);
    }

    public String secondGrade(int actorPosition) {
        return String.format("%.2f", (actorList.get(actorPosition).getPerformances().get(2).getGrade()
                + actorList.get(actorPosition).getPerformances().get(3).getGrade()) / 2);
    }

    public String firstSemesterAverage(int actorPosition) {
        return String.format("%.2f", (actorList.get(actorPosition).getPerformances().get(0).getGrade()
                + actorList.get(actorPosition).getPerformances().get(1).getGrade()
                + actorList.get(actorPosition).getPerformances().get(2).getGrade()
                + actorList.get(actorPosition).getPerformances().get(3).getGrade()) / 4);
    }

    public String thirdGrade(int actorPosition) {
        return String.format("%.2f", (actorList.get(actorPosition).getPerformances().get(5).getGrade()
                + actorList.get(actorPosition).getPerformances().get(6).getGrade()) / 2);
    }

    public String fourthGrade(int actorPosition) {
        return String.format("%.2f", (actorList.get(actorPosition).getPerformances().get(7).getGrade()
                + actorList.get(actorPosition).getPerformances().get(8).getGrade()) / 2);
    }

    public String secondSemesterAverage(int actorPosition) {
        return String.format("%.2f", (actorList.get(actorPosition).getPerformances().get(5).getGrade()
                + actorList.get(actorPosition).getPerformances().get(6).getGrade()
                + actorList.get(actorPosition).getPerformances().get(7).getGrade()
                + actorList.get(actorPosition).getPerformances().get(8).getGrade()) / 4);
    }

    public void loadGrades() {
        Discipline disciplineAux = new Discipline();
        disciplineAux.setId(disciplineID);

        for (Actor actor : actorList) {
            actor.setPerformances(performanceBO.actorGradesPerReferenceDiscipline(actor.getId(),
                    disciplineID, Reference.UNITY, unityID));
            if (actor.getPerformances() == null || actor.getPerformances().isEmpty()) {
                for (int i = 1; i <= grandeQuantity; i++) {
                    Performance performance = new Performance(actor, disciplineAux,
                            Reference.UNITY, unityID, 0F);
                    performance.setSeq(i);
                    performanceBO.create(performance);
                    actor.getPerformances().add(performance);
                }
            }
        }
    }

    public void saveGrades() {
        try {
            for (Actor actor : actorList) {
                for (Performance performance : actor.getPerformances()) {
                    performanceBO.edit(performance);
                }
            }
            addInfoMessage("performanceForm:gradesGroup", "Operação realizada com sucesso", null);
        } catch (Exception ex) {
            addErrorMessage("performanceForm:gradesGroup", "Operação não pôde ser realizada", null);
        }
    }

    public void export() {
        if (!actorList.isEmpty() && !disciplineList.isEmpty()) {
            List<String> namesList = new ArrayList<String>();
            for (Actor actor : actorList) {
                namesList.add(((Human) actor.getPerson()).getName());
            }

            List<String> disciplinesName = new ArrayList<String>();
            for (SelectItem discipline : disciplineList) {
                if (!discipline.getLabel().equals(" ")) {
                    disciplinesName.add(discipline.getLabel());
                }
            }

            String filePath = performanceBO.export(namesList, actorList.get(0).getUnity().getName(), disciplinesName);

            FacesContext facesContext = ServiceUtil.getFacesContext();
            ExternalContext externalContext = facesContext.getExternalContext();
            HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

            File file = new File(filePath);
            BufferedInputStream input = null;
            BufferedOutputStream output = null;

            try {
                input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
                response.reset();
                response.setHeader("Content-Type", "application/pdf");
                response.setHeader("Content-Length", String.valueOf(file.length()));
                response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
                output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
                byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
                int length;
                while ((length = input.read(buffer)) > 0) {
                    output.write(buffer, 0, length);
                }
                output.flush();
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                close(output);
                close(input);
            }
            facesContext.responseComplete();
        }
    }
    
    public void export2() {
        if (!actorList.isEmpty() && !disciplineList.isEmpty()) {
            List<String> namesList = new ArrayList<String>();
            for (Actor actor : actorList) {
                namesList.add(((Human) actor.getPerson()).getName());
            }

            String filePath = performanceBO.export2(namesList, actorList.get(0).getUnity().getName(), disciplineBO.find(disciplineID).getName());

            FacesContext facesContext = ServiceUtil.getFacesContext();
            ExternalContext externalContext = facesContext.getExternalContext();
            HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

            File file = new File(filePath);
            BufferedInputStream input = null;
            BufferedOutputStream output = null;

            try {
                input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
                response.reset();
                response.setHeader("Content-Type", "application/pdf");
                response.setHeader("Content-Length", String.valueOf(file.length()));
                response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
                output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
                byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
                int length;
                while ((length = input.read(buffer)) > 0) {
                    output.write(buffer, 0, length);
                }
                output.flush();
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                close(output);
                close(input);
            }
            facesContext.responseComplete();
        }
    }

    private static void close(Closeable resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public Long getDisciplineID() {
        return disciplineID;
    }

    public void setDisciplineID(Long disciplineID) {
        this.disciplineID = disciplineID;
    }

    public List<SelectItem> getDisciplineList() {
        return disciplineList;
    }

    public void setDisciplineList(List<SelectItem> disciplineList) {
        this.disciplineList = disciplineList;
    }

    public Long getOrganizationID() {
        return organizationID;
    }

    public void setOrganizationID(Long organizationID) {
        this.organizationID = organizationID;
    }

    public SessionBean getSessionBean() {
        return sessionBean;
    }

    public void setSessionBean(SessionBean sessionBean) {
        this.sessionBean = sessionBean;
    }

    public Long getUnityID() {
        return unityID;
    }

    public void setUnityID(Long unityID) {
        this.unityID = unityID;
    }

    public List<SelectItem> getUnityList() {
        return unityList;
    }

    public void setUnityList(List<SelectItem> unityList) {
        this.unityList = unityList;
    }

    public List<Actor> getActorList() {
        return actorList;
    }

    public void setActorList(List<Actor> actorList) {
        this.actorList = actorList;
    }

    public boolean isConfigureGradesVisible() {
        return configureGradesVisible;
    }

    public void setConfigureGradesVisible(boolean configureGradesVisible) {
        this.configureGradesVisible = configureGradesVisible;
    }

    public int getGrandeQuantity() {
        return grandeQuantity;
    }

    public void setGrandeQuantity(int grandeQuantity) {
        this.grandeQuantity = grandeQuantity;
    }
}
